package data;

import java.util.*;

import prj3.*;
import util.KeplerLaws;

public class Serializer
{
	public class Parameters 
	{   
		public Parameters(double gst, double gsp, int ts, double at, double ec, java.util.GregorianCalendar sd,
				java.util.GregorianCalendar ed, double latmin, double latmax, double longmin,
				double longmax, double geotol, int mintol, int prec){
			gridStepTheta = gst;
			gridStepPhi = gsp;
			timeStep = ts;
			axialTilt = at;
			eccentricity = ec;
			startDate = sd;
			endDate = ed;
			latitudeMin = latmin;
			latitudeMax = latmax;
			longitudeMin = longmin;
			longitudeMax = longmax;
			geoTolerance = geotol;
			minutesTolerance = mintol;
			precisionDigits = prec;		
		}

		public double gridStepTheta;
		public double gridStepPhi;
		public int timeStep;
		public double axialTilt;
		public double eccentricity;
		public java.util.GregorianCalendar startDate;
		public java.util.GregorianCalendar endDate;
		public double latitudeMin;
		public double latitudeMax;
		public double longitudeMin;
		public double longitudeMax;
		public double geoTolerance;
		public int minutesTolerance;
		public int precisionDigits;
	}

	private int m_StorageGeoStride;
	private int m_StorageTimeStride;
	private Database m_Database;

	public Serializer( int storageGeoStride, int storageTimeStride, Database db )
	{
		m_StorageGeoStride = storageGeoStride;
		m_StorageTimeStride = storageTimeStride;
		m_Database = db;
	}

	public BufferedEarthGrid load( Parameters p ) throws InsufficientDataException
	{
		// should buffer all data before starting to display -- don't know if we'll 
		// have to abort and run a simulation if some data isn't present until all
		// data has been retrieved.
		// Thus we set the buffer size to be arbitrarily large
		int bufferSize = 2000000000;

		Interpolator interp = new Interpolator( p.geoTolerance,
				p.minutesTolerance, 
				p.precisionDigits,
				p.axialTilt,
				p.eccentricity,
				m_Database );
		BufferedEarthGrid grid = new BufferedEarthGrid( /* RADIUS */ 6378, 
				(float) p.gridStepTheta,
				(float) p.gridStepPhi,
				(float) p.eccentricity,
				(float)p.axialTilt, 
				bufferSize );

		KeplerLaws kLaws = new KeplerLaws(p.startDate.get(GregorianCalendar.DAY_OF_MONTH),
				p.startDate.get(GregorianCalendar.MONTH), (float)p.eccentricity, (float)p.axialTilt);



		// time loop
		for( GregorianCalendar time = (GregorianCalendar) p.startDate.clone();
		time.getTime().getTime() < p.endDate.getTime().getTime();
		time.add( Calendar.MINUTE, p.timeStep ) ) {

			grid.setSimulatedTimeStep( time );
			grid.setSunAngle( kLaws.getSunAngle());
			grid.setSunDistance(kLaws.getDistance());
			grid.setSunLatitude(kLaws.getCurrentTilt());
			grid.setSunOrbitAngle(kLaws.getRealAnomaly());


			// walk all cells and add a sample at each one
			Iterator iter = grid.getAllCells().iterator();
			while( iter.hasNext() ) {

				BufferedEarthCell cell = (BufferedEarthCell) iter.next();
				SphericalCoordinate coord = (SphericalCoordinate) cell.getCoordinate();
				float val = (float) interp.interpolatedValue( coord.getLatitude(),
						coord.getLongitude(),
						time );
				cell.setValue(val);
				cell.switchValues();

			}
			kLaws.step(p.timeStep);

		}

		return grid;
	}
}
